package be.mjosoft.ios.apn;

import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import java.util.HashMap;
import java.util.Map;

/**
 * This class represents a message that will be sent to the Apple Push Notification Service.
 * @author mj
 */
public class APNMessage
{
	protected Map<String, Object> aps;
	protected Map<String, Object> jSon;

	/**
	 * Constructor.
	 */
	public APNMessage()
	{
		aps = new HashMap<String, Object>();
		jSon = new HashMap<String, Object>();
		jSon.put("aps", aps);
	}

	/**
	 * Constructor.
	 * @param alert the alert part of the message.
	 */
	public APNMessage(String alert)
	{
		this();
		setAlert(alert);
	}

	/**
	 * Constructor.
	 * @param alert the alert part of the message.
	 */
	public APNMessage(CustomAlert alert)
	{
		this();
		setCustomAlert(alert);
	}

	/**
	 * Constructor.
	 * @param alert the alert part of the message.
	 * @param badge the badge part of the message.
	 */
	public APNMessage(String alert, int badge)
	{
		this();
		setAlert(alert);
		setBadge(badge);
	}

	/**
	 * Constructor.
	 * @param alert the alert part of the message.
	 * @param badge the badge part of the message.
	 */
	public APNMessage(CustomAlert alert, int badge)
	{
		this();
		setCustomAlert(alert);
		setBadge(badge);
	}

	/**
	 * Constructor.
	 * @param alert the alert part of the message.
	 * @param sound the sound part of the message.
	 */
	public APNMessage(String alert, String sound)
	{
		this();
		setAlert(alert);
		setSound(sound);
	}

	/**
	 * Constructor.
	 * @param alert the alert part of the message.
	 * @param sound the sound part of the message.
	 */
	public APNMessage(CustomAlert alert, String sound)
	{
		this();
		setCustomAlert(alert);
		setSound(sound);
	}

	/**
	 * Constructor.
	 * @param badge the badge part of the message.
	 */
	public APNMessage(int badge)
	{
		this();
		setBadge(badge);
	}

	/**
	 * Constructor.
	 * @param badge the badge part of the message.
	 * @param sound the sound part of the message.
	 */
	public APNMessage(int badge, String sound)
	{
		this();
		setBadge(badge);
		setSound(sound);
	}

	/**
	 * Constructor.
	 * @param alert the alert part of the message.
	 * @param badge the badge part of the message.
	 * @param sound the sound part of the message.
	 */
	public APNMessage(String alert, int badge, String sound)
	{
		this();
		setAlert(alert);
		setBadge(badge);
		setSound(sound);
	}

	/**
	 * Constructor.
	 * @param alert the alert part of the message.
	 * @param badge the badge part of the message.
	 * @param sound the sound part of the message.
	 */
	public APNMessage(CustomAlert alert, int badge, String sound)
	{
		this();
		setCustomAlert(alert);
		setBadge(badge);
		setSound(sound);
	}

	/**
	 * Initialises the alert part of the message.
	 * @param alert the alert part of the message.
	 */
	public void setAlert(String alert)
	{
		aps.put("alert", alert);
	}

	/**
	 * Initialises the alert part of the message.
	 * @param alert the alert part of the message.
	 */
	public void setCustomAlert(CustomAlert alert)
	{
		aps.put("alert", alert);
	}

	/**
	 * Returns the alert part of the message.
	 * @return the alert part of the message or null if no alert part.
	 */
	public String getAlert()
	{
		Object o = aps.get("alert");
		if(o != null && o instanceof String){
			return (String) o;
		}
		return null;
	}

	/**
	 * Returns the alert part of the message.
	 * @return the alert part of the message or null if no alert part.
	 */
	public CustomAlert getCustomAlert()
	{
		Object o = aps.get("alert");
		if(o != null && o instanceof CustomAlert){
			return (CustomAlert) o;
		}
		return null;
	}

	/**
	 * Initialises the badge part of the message.
	 * @param badge the badge part of the message.
	 */
	public void setBadge(int badge)
	{
		aps.put("badge", badge);
	}

	/**
	 * Returns the badge part of the message.
	 * @return the badge part of the message or null if no badge part.
	 */
	public Integer getBadge()
	{
		return (Integer) aps.get("badge");
	}

	/**
	 * Increments the badge value by the amount of increment.
	 * If the badge value was null it wil be now 0 + increment.
	 * @param increment the amount to add to the badge value.
	 * @return the new badge value.
	 */
	public int incrementBadge(int increment)
	{
		Integer b = getBadge();
		if(b == null){
			b = 0;
		}
		b += increment;
		setBadge(b);
		return b;
	}

	/**
	 * Increments the badge value by 1.
	 * If the badge value was null it wil be now 0 + 1.
	 * @return the new badge value.
	 */
	public int incrementBadge()
	{
		return incrementBadge(1);
	}

	/**
	 * Initialises the sound part of the message.
	 * @param sound the sound part of the message.
	 */
	public void setSound(String sound)
	{
		aps.put("sound", sound);
	}

	/**
	 * Returns the sound part of the message.
	 * @return the sound part of the message or null if no sound part.
	 */
	public String getSound()
	{
		return (String) aps.get("sound");
	}

	/**
	 * Initialises a custom part of the message.
	 * @param messageKey the key of the custom part.
	 * @param messageValue the value of the message part.
	 */
	public void setCustomMessage(String messageKey, Object messageValue)
	{
		jSon.put(messageKey, messageValue);
	}

	/**
	 * Returns a custom part of the message.
	 * @param messageKey the key of the custom part.
	 * @return a custom part of the message or null if this custom part is not present.
	 */
	public Object getCustomMessage(String messageKey)
	{
		return jSon.get(messageKey);
	}

	/**
	 * Removes a custom part from the message.
	 * @param messageKey the key of the custom part.
	 * @return the custom part removed from the message or null if this custom part is not present.
	 */
	public Object removeCustomMessage(String messageKey)
	{
		return jSon.remove(messageKey);
	}

	/**
	 * Removes all custom parts from the message.
	 */
	public void removeAllCustomMessages()
	{
		jSon.clear();
		jSon.put("aps", aps);
	}

	/**
	 * Returns a JSon representation of the message.
	 * @return a JSon representation of the message.
	 */
	@Override
	public String toString()
	{
		Gson g = new Gson();
		return g.toJson(jSon);
	}

	/**
	 * This class is used for custom alert.
	 */
	public static class CustomAlert
	{
		@SerializedName(value="body")
		protected String body;

		@SerializedName(value="action-loc-key")
		protected String localizedActionKey;

		@SerializedName(value="loc-key")
		protected String localizedMessageKey;

		@SerializedName(value="loc-args")
		protected String []localizedMessageArguments;

		/**
		 * @return the body
		 */
		public String getBody()
		{
			return body;
		}

		/**
		 * @param body the body to set
		 */
		public void setBody(String body)
		{
			this.body = body;
		}

		/**
		 * Returns the action-loc-key part of the message.
		 * @return the action-loc-key part of the message or null if no action-loc-args part.
		 */
		public String getLocalizedActionKey()
		{
			return localizedActionKey;
		}

		/**
		 * Initialises the action-loc-key part of the message.
		 * @param localizedActionKey the action-loc-key part of the message.
		 */
		public void setLocalizedActionKey(String localizedActionKey)
		{
			this.localizedActionKey = localizedActionKey;
		}

		/**
		 * Returns the loc-key part of the message.
		 * @return the loc-key part of the message or null if no loc-key part.
		 */
		public String getLocalizedMessageKey()
		{
			return localizedMessageKey;
		}

		/**
		 * Initialises the loc-key part of the message.
		 * @param localizedMessageKey the loc-key part of the message.
		 */
		public void setLocalizedMessageKey(String localizedMessageKey)
		{
			this.localizedMessageKey = localizedMessageKey;
		}

		/**
		 * Returns the loc-args part of the message.
		 * @return the loc-args part of the message or null if no loc-args part.
		 */
		public String[] getLocalizedMessageArguments()
		{
			return localizedMessageArguments;
		}

		/**
		 * Initialises the loc-args part of the message.
		 * @param localizedMessageArguments the loc-args part of the message.
		 */
		public void setLocalizedMessageArguments(String ... localizedMessageArguments)
		{
			this.localizedMessageArguments = localizedMessageArguments;
		}
	}
}